home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Languages / PowerMacOberon 1.2 / Source / Elems / LinkElems.Mod (.txt) < prev    next >
Oberon Text  |  1995-08-22  |  12KB  |  347 lines

  1. Syntax10.Scn.Fnt
  2. StampElems
  3. Alloc
  4. 3 Aug 95
  5. Syntax10b.Scn.Fnt
  6. Syntax10m.Scn.Fnt
  7. Syntax10i.Scn.Fnt
  8. MarkElems
  9. Alloc
  10. MODULE LinkElems;  (** HM 
  11. IMPORT
  12.     Files, Fonts, Display, Input, Viewers, Texts, TextFrames, MenuViewers, TextPrinter, Oberon, PopupElems, MarkElems, FoldElems;
  13. CONST
  14.     left =2; middle = 1; right = 0;
  15.     pixel = LONG(10000);
  16.     stdMenu = "System.Close  System.Copy  System.Grow  Edit.Search  Edit.Replace  Edit.Store ";
  17.     Elem* = POINTER TO ElemDesc;
  18.     ElemDesc* = RECORD (Texts.ElemDesc)
  19.         file*: ARRAY 32 OF CHAR;
  20.         key*: LONGINT
  21.     END;
  22.     FollowMsg* = RECORD (Texts.ElemMsg) f*: Display.Frame END;
  23.     Menu* = POINTER TO MenuDesc;
  24.     MenuDesc* = RECORD (PopupElems.ElemDesc)
  25.     END;
  26.     Frame = POINTER TO FrameDesc;
  27.     FrameDesc = RECORD (TextFrames.FrameDesc)
  28.         e: Elem
  29.     END;
  30.     searchKey: LONGINT;    (*key of mark element searched in FollowLink; used in Check*)
  31.     hint: TextFrames.Frame;    (*suggests frame to be used for links emanating from a link menu*)
  32.     icon, invIcon: Display.Pattern; (* x = 0, y = 3, w = 9, h = 8 *)
  33.     w: Texts.Writer;
  34. PROCEDURE^ New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
  35. PROCEDURE 
  36. GetSelection (VAR f: TextFrames.Frame);
  37.     (* return frame f with the latest text selection*)
  38.     VAR v: Viewers.Viewer; f0: Display.Frame; time: LONGINT; x: INTEGER;
  39. BEGIN
  40.     x := 0; time := -1; f := NIL;
  41.     WHILE x < Display.Width DO
  42.         v := Viewers.This(x, 0);
  43.         WHILE v.state > 1 DO
  44.             f0 := v.dsc;
  45.             WHILE f0 # NIL DO
  46.                 WITH f0: TextFrames.Frame DO
  47.                     IF f0.hasSel & (f0.time > time) THEN f := f0; time := f.time END
  48.                 ELSE
  49.                 END;
  50.                 f0 := f0.next
  51.             END;
  52.             v := Viewers.Next(v)
  53.         END;
  54.         x := x + v.W
  55. END GetSelection;
  56. PROCEDURE 
  57. GetFileName (t: Texts.Text; VAR name: ARRAY OF CHAR);
  58.     (* return the name of the viewer which contains text t*)
  59.     VAR v, V: Viewers.Viewer; f: Display.Frame; s: Texts.Scanner; x: INTEGER; 
  60. BEGIN
  61.     V := NIL; x := 0;
  62.     WHILE x < Display.Width DO
  63.         v := Viewers.This(x, 0);
  64.         WHILE v.state > 1 DO
  65.             f := v.dsc;
  66.             WHILE f # NIL DO
  67.                 IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = t) THEN V := v END;
  68.                 f := f.next
  69.             END;
  70.             v := Viewers.Next(v)
  71.         END;
  72.         x := x + v.W
  73.     END;
  74.     IF V # NIL THEN
  75.         Texts.OpenScanner(s, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
  76.         IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, name) ELSE name[0] := 0X END
  77. END GetFileName;
  78. PROCEDURE 
  79. GetFrame (name: ARRAY OF CHAR; VAR f: TextFrames.Frame);
  80.     VAR x: INTEGER; v: Viewers.Viewer; s: Texts.Scanner;
  81. BEGIN
  82.     IF hint # NIL THEN f := hint
  83.     ELSE
  84.         x := 0; f := NIL;
  85.         WHILE x < Display.Width DO
  86.             v := Viewers.This(x, 0);
  87.             WHILE v.state > 1 DO
  88.                 IF (v.dsc # NIL) & (v.dsc IS TextFrames.Frame) THEN
  89.                     Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
  90.                     IF s.s = name THEN f := v.dsc.next(TextFrames.Frame); RETURN END
  91.                 END;
  92.                 v := Viewers.Next(v)
  93.             END;
  94.             x := x + v.W
  95.         END
  96. END GetFrame;
  97. PROCEDURE 
  98. GetDsr (f: Display.Frame; pos: LONGINT; fnt: Fonts.Font; VAR dsr: INTEGER);
  99.     VAR p: TextFrames.Parc; beg: LONGINT;
  100. BEGIN
  101.     IF f = NIL THEN
  102.         IF fnt = NIL THEN dsr := 0 ELSE dsr := - fnt.minY END
  103.     ELSE
  104.         TextFrames.ParcBefore(f(TextFrames.Frame).text, pos, p, beg);
  105.         dsr := SHORT(p.dsr DIV TextFrames.Unit)
  106. END GetDsr;
  107. PROCEDURE 
  108. CollectMarks (pop: Menu; f0: Display.Frame);
  109.     (* Fill popup menu with all mark elements in f0.next.text*)
  110.     VAR r: Texts.Reader; s: Texts.Scanner; ch: CHAR; f: TextFrames.Frame; mark: MarkElems.Elem; link: Elem; n: INTEGER;
  111.         file: ARRAY 32 OF CHAR;
  112. BEGIN
  113.     pop.menu := TextFrames.Text("");
  114.     IF (f0.next = NIL) OR ~ (f0.next IS TextFrames.Frame) THEN
  115.         Texts.WriteString(w, "link menu not in menu bar of a text viewer"); Texts.WriteLn(w); Texts.WriteLn(w)
  116.     ELSE
  117.         f := f0.next(TextFrames.Frame); hint := f; GetFileName(f.text, file); n := 0;
  118.         Texts.OpenReader(r, f.text, 0); Texts.ReadElem(r);
  119.         WHILE ~ r.eot DO
  120.             IF r.elem IS MarkElems.Elem THEN
  121.                 mark := r.elem(MarkElems.Elem);
  122.                 link := New(file, mark.key);
  123.                 Texts.WriteElem(w, link); Texts.Write(w, " ");
  124.                 Texts.OpenScanner(s, f.text, Texts.Pos(r)); Texts.Scan(s);
  125.                 WHILE ~s.eot & (s.class # Texts.Name) DO Texts.Scan(s) END;
  126.                 IF ~s.eot THEN Texts.WriteString(w, s.s); Texts.WriteLn(w); INC(n)
  127.                 END
  128.             END;
  129.             Texts.ReadElem(r)
  130.         END;
  131.         IF n = 0 THEN Texts.WriteString(w, "no marks"); Texts.WriteLn(w) END;
  132.         IF n <= 1 THEN Texts.WriteLn(w) END;
  133.     END;
  134.     Texts.Append(pop.menu, w.buf); PopupElems.MeasureMenu(pop)
  135. END CollectMarks;
  136. PROCEDURE 
  137. ShowPos (f: TextFrames.Frame; pos: LONGINT);
  138.     VAR beg, end, delta: LONGINT;
  139. BEGIN delta := 200;
  140.     LOOP beg := f.org; end := TextFrames.Pos(f, f.X + f.W, f.Y);
  141.         IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END;
  142.         TextFrames.Show(f, pos - delta); delta := delta DIV 2
  143.     END;
  144.     TextFrames.SetSelection(f, pos, pos + 1)
  145. END ShowPos;
  146. PROCEDURE 
  147. Check (e: Texts.Elem): BOOLEAN;
  148. BEGIN RETURN (e IS MarkElems.Elem) & (e(MarkElems.Elem).key = searchKey)
  149. END Check;
  150. PROCEDURE 
  151. FollowLink* (file: ARRAY OF CHAR; key: LONGINT; backF: Display.Frame; backE: Texts.Elem);
  152.     VAR v: Viewers.Viewer; menu: TextFrames.Frame; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer;
  153.         mark: Texts.Elem; f: TextFrames.Frame;
  154. BEGIN
  155.     GetFrame(file, f);
  156.     IF f = NIL THEN
  157.         f := TextFrames.NewText(TextFrames.Text(file), 0);
  158.         Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
  159.         IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(file, stdMenu)
  160.         ELSE menu := TextFrames.NewMenu(file, "");
  161.             NEW(t); Texts.Open(t, "Edit.Menu.Text");
  162.             NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, 0, t.len, buf); Texts.Append(menu.text, buf)
  163.         END;
  164.         v := MenuViewers.New(menu, f, TextFrames.menuH, x, y)
  165.     END;
  166.     searchKey := key;
  167.     FoldElems.FindElem(f.text, 0, Check, mark);
  168.     IF mark # NIL THEN
  169.         ShowPos(f, Texts.ElemPos(mark));
  170.         IF backF # NIL THEN MarkElems.backF := backF(TextFrames.Frame) ELSE MarkElems.backF := NIL END; 
  171.         MarkElems.backE := backE
  172. END FollowLink;
  173. PROCEDURE 
  174. Edit (e: Elem);
  175.     VAR t: Texts.Text; v: MenuViewers.Viewer; f: Frame; x, y: INTEGER;
  176. BEGIN
  177.     t := TextFrames.Text("");
  178.     Texts.WriteString(w, e.file); Texts.Write(w, " "); Texts.WriteInt(w, e.key, 0);
  179.     Texts.Append(t, w.buf);
  180.     NEW(f); f.e := e; TextFrames.Open(f, t, 0);
  181.     Oberon.AllocateSystemViewer(0, x, y);
  182.     v := MenuViewers.New(
  183.         TextFrames.NewMenu("LinkElem", "System.Close  LinkElems.Update "),
  184.         f, TextFrames.menuH, x, y)
  185. END Edit;
  186. PROCEDURE 
  187. Handle* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  188.     VAR e1: Elem; x, y, dsr, i: INTEGER; keys: SET; ch: CHAR; follow: FollowMsg;
  189. BEGIN
  190.     WITH e: Elem DO
  191.         WITH m: Texts.FileMsg DO
  192.             IF m.id = Texts.load THEN
  193.                 i := 0; REPEAT Files.Read(m.r, ch); e.file[i] := ch; INC(i) UNTIL ch = 0X;
  194.                 Files.ReadLInt(m.r, e.key)
  195.             ELSE (*Texts.store*)
  196.                 i := 0; REPEAT ch := e.file[i]; Files.Write(m.r, ch); INC(i) UNTIL ch = 0X;
  197.                 Files.WriteLInt(m.r, e.key)
  198.             END
  199.         | m: Texts.CopyMsg DO
  200.             IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END;
  201.             Texts.CopyElem(e, e1); COPY(e.file, e1.file); e1.key := e.key
  202.         | m: Texts.IdentifyMsg DO
  203.             m.mod := "LinkElems"; m.proc := "Alloc"
  204.         | m: TextFrames.DisplayMsg DO
  205.             IF ~m.prepare THEN
  206.                 GetDsr(m.frame, m.pos, m.fnt, dsr);
  207.                 Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.paint)
  208.             END
  209.         | m: TextPrinter.PrintMsg DO
  210.             IF m.prepare THEN e.W := 1 ELSE e.W := 10 * pixel END
  211.         | m: TextFrames.TrackMsg DO
  212.                 IF middle IN m.keys THEN
  213.                     IF m.frame # NIL THEN
  214.                         GetDsr(m.frame, m.pos, m.fnt, dsr);
  215.                         Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert);
  216.                         Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
  217.                         REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
  218.                             Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
  219.                         UNTIL keys = {};
  220.                         Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
  221.                         Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert)
  222.                     END;
  223.                     IF m.keys = {middle} THEN follow.f := m.frame; e.handle(e, follow)
  224.                     ELSIF m.keys = {middle, right} THEN Edit(e)
  225.                     END
  226.                 END
  227.         | m: FollowMsg DO
  228.             FollowLink(e.file, e.key, m.f, e)
  229.         ELSE
  230.         END
  231. END Handle;
  232. PROCEDURE 
  233. HandleMenu* (e: Texts.Elem; VAR m: Texts.ElemMsg);
  234.     VAR e1: Menu;
  235. BEGIN
  236.     WITH e: Menu DO
  237.         WITH
  238.           m: Texts.IdentifyMsg DO
  239.             m.mod := "LinkElems"; m.proc := "AllocMenu"
  240.         | m: Texts.CopyMsg DO
  241.             NEW(e1); m.e := e1; PopupElems.Handle(e, m)
  242.         | m: TextFrames.DisplayMsg DO
  243.             IF m.prepare THEN
  244.                 e.W := 13 * pixel; e.H := LONG(TextFrames.menuH-1) * pixel;
  245.             ELSE e.name := ""; PopupElems.Handle(e, m);
  246.                 Display.CopyPattern(Display.white, icon, m.X0+2, m.Y0+3, Display.paint)
  247.             END
  248.         | m: TextFrames.TrackMsg DO
  249.             IF middle IN m.keys THEN
  250.                 CollectMarks(e, m.frame); PopupElems.Handle(e, m); hint := NIL
  251.             END
  252.         ELSE PopupElems.Handle(e, m)
  253.         END
  254. END HandleMenu;
  255. PROCEDURE 
  256. Alloc*;
  257.     VAR e: Elem;
  258. BEGIN
  259.     NEW(e); e.handle := Handle; Texts.new := e
  260. END Alloc;
  261. PROCEDURE 
  262. AllocMenu*;
  263.     VAR e: Menu;
  264. BEGIN
  265.     NEW(e); e.handle := HandleMenu; Texts.new := e
  266. END AllocMenu;
  267. PROCEDURE 
  268. New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
  269.     VAR e: Elem;
  270. BEGIN
  271.     NEW(e); e.W := 10 * pixel; e.H := 11 * pixel; e.handle := Handle; COPY(file, e.file); e.key := key;
  272.     RETURN e
  273. END New;
  274. PROCEDURE 
  275. Insert*;
  276.     VAR link: Elem; mark: MarkElems.Elem; fromT, toT: Texts.Text; toPos, end, time: LONGINT;
  277.         r: Texts.Reader; ch: CHAR; m: TextFrames.InsertElemMsg; f: TextFrames.Frame;
  278. BEGIN
  279.     f := Oberon.FocusViewer.dsc(TextFrames.Frame);
  280.     IF f.hasCar THEN fromT := f.text ELSE fromT := f.next(TextFrames.Frame).text END;
  281.     Oberon.GetSelection(toT, toPos, end, time);
  282.     IF time >= 0 THEN
  283.         link := New("", 0); GetFileName(toT, link.file);
  284.         Texts.OpenReader(r, toT, toPos); Texts.Read(r, ch);
  285.         m.e := link; Viewers.Broadcast(m);
  286.         IF (ch = Texts.ElemChar) & (r.elem IS MarkElems.Elem) THEN
  287.             link.key := r.elem(MarkElems.Elem).key
  288.         ELSE
  289.             IF (fromT = toT) & (Texts.ElemPos(link) <= toPos) THEN INC(toPos) END;
  290.             mark := MarkElems.New(); link.key := mark.key;
  291.             Texts.WriteElem(w, mark); Texts.Insert(toT, toPos, w.buf)
  292.         END
  293. END Insert;
  294. PROCEDURE 
  295. InsertMenu*;
  296.     VAR e: Menu; insert: TextFrames.InsertElemMsg;
  297. BEGIN
  298.     NEW(e); e.handle := HandleMenu; e.name := ""; e.menu := TextFrames.Text(""); e.small := TRUE; 
  299.     PopupElems.MeasureMenu(e);
  300.     insert.e := e; Viewers.Broadcast(insert)
  301. END InsertMenu;
  302. PROCEDURE 
  303. Update*;
  304.     VAR f: Frame; t: Texts.Text; s: Texts.Scanner; r: Texts.Reader; ch: CHAR;
  305. BEGIN
  306.     IF (Oberon.Par.frame = Oberon.Par.vwr.dsc) & (Oberon.Par.frame.next IS Frame) THEN
  307.         f := Oberon.Par.frame.next(Frame);
  308.         Texts.OpenScanner(s, f.text, 0); Texts.Scan(s);
  309.         IF s.class = Texts.Name THEN
  310.             COPY(s.s, f.e.file); Texts.Scan(s);
  311.             IF s.class = Texts.Int THEN
  312.                 f.e.key := s.i;
  313.                 t := Oberon.Par.frame(TextFrames.Frame).text;
  314.                 Texts.OpenReader(r, t, t.len-1); Texts.Read(r, ch);
  315.                 IF ch = "!" THEN Texts.Delete(t, t.len-1, t.len) END
  316.             END
  317.         END
  318. END Update;
  319. PROCEDURE 
  320. InitIcon;
  321.     VAR line: ARRAY 9 OF SET;
  322. BEGIN
  323.     line[8] := {4};
  324.     line[7] := {3, 5};
  325.     line[6] := {2, 6};
  326.     line[5] := {1..3, 5..7};
  327.     line[4] := {3, 5};
  328.     line[3] := {3, 5};
  329.     line[2] := {3, 5};
  330.     line[1] := {3..5};
  331.     icon := Display.NewPattern(line, 9, 8);
  332.     line[8] := {4};
  333.     line[7] := {3..5};
  334.     line[6] := {2..6};
  335.     line[5] := {1..7};
  336.     line[4] := {3..5};
  337.     line[3] := {3..5};
  338.     line[2] := {3..5};
  339.     line[1] := {3..5};
  340.     invIcon := Display.NewPattern(line, 9, 8)
  341. END InitIcon;
  342. BEGIN
  343.     Texts.OpenWriter(w);
  344.     InitIcon;
  345.     hint := NIL
  346. END LinkElems.
  347.